﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

namespace RFEngine.Graphics.Effects
{
    public sealed class SpriteEffect : Effect
    {
        #region Fields

        private EffectParameter WorldParameter;
        private EffectParameter ViewParameter;
        private EffectParameter ProjectionParameter;
        private EffectParameter EnableTextureParameter;
        private EffectParameter TextureParameter;

        private bool _EnableTexture = true;

        private Matrix _World;
        private Matrix _View = Matrix.Identity;
        private Matrix _Projection = Matrix.Identity;
        private Texture2D _Texture;

        #region Static and Constants

        #region Platform Specific Code

        #region Windows Code

        #if WINDOWS

        private static byte[] EFFECT_CODE = new byte[]
        {
            1,9,255,254,192,2,0,0,0,0,0,0,3,0,0,0,
            2,0,0,0,96,0,0,0,0,0,0,0,0,0,0,0,
            4,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,
            0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
            0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
            0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
            0,0,0,0,0,0,0,0,6,0,0,0,87,111,114,108,
            100,0,144,0,3,0,0,0,2,0,0,0,200,0,0,0,
            0,0,0,0,0,0,0,0,4,0,0,0,4,0,0,0,
            0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
            0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
            0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
            0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
            5,0,0,0,86,105,101,119,0,0,0,0,3,0,0,0,
            2,0,0,0,48,1,0,0,0,0,0,0,0,0,0,0,
            4,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,
            0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
            0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
            0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
            0,0,0,0,0,0,0,0,11,0,0,0,80,114,111,106,
            101,99,116,105,111,110,0,0,1,0,0,0,0,0,0,0,
            96,1,0,0,0,0,0,0,0,0,0,0,1,0,0,0,
            1,0,0,0,0,0,0,0,14,0,0,0,69,110,97,98,
            108,101,84,101,120,116,117,114,101,0,0,0,5,0,0,0,
            4,0,0,0,140,1,0,0,0,0,0,0,0,0,0,0,
            1,0,0,0,8,0,0,0,84,101,120,116,117,114,101,0,
            10,0,0,0,4,0,0,0,104,2,0,0,0,0,0,0,
            0,0,0,0,2,0,0,0,5,0,0,0,4,0,0,0,
            0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,
            2,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,
            0,0,0,0,1,0,0,0,1,0,0,0,2,0,0,0,
            2,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,
            0,0,0,0,1,0,0,0,1,0,0,0,2,0,0,0,
            2,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,
            0,0,0,0,1,0,0,0,1,0,0,0,4,0,0,0,
            164,0,0,0,0,1,0,0,176,1,0,0,172,1,0,0,
            171,0,0,0,0,1,0,0,200,1,0,0,196,1,0,0,
            170,0,0,0,0,1,0,0,232,1,0,0,228,1,0,0,
            169,0,0,0,0,1,0,0,8,2,0,0,4,2,0,0,
            15,0,0,0,116,101,120,116,117,114,101,83,97,109,112,108,
            101,114,0,0,3,0,0,0,16,0,0,0,4,0,0,0,
            0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,
            15,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,
            0,0,0,0,3,0,0,0,112,48,0,0,8,0,0,0,
            68,101,102,97,117,108,116,0,6,0,0,0,1,0,0,0,
            4,0,0,0,5,0,0,0,4,0,0,0,32,0,0,0,
            0,0,0,0,0,0,0,0,108,0,0,0,136,0,0,0,
            0,0,0,0,0,0,0,0,212,0,0,0,240,0,0,0,
            0,0,0,0,0,0,0,0,64,1,0,0,92,1,0,0,
            0,0,0,0,0,0,0,0,116,1,0,0,136,1,0,0,
            0,0,0,0,0,0,0,0,152,1,0,0,36,2,0,0,
            0,0,0,0,0,0,0,0,180,2,0,0,0,0,0,0,
            1,0,0,0,172,2,0,0,0,0,0,0,2,0,0,0,
            146,0,0,0,0,0,0,0,128,2,0,0,124,2,0,0,
            147,0,0,0,0,0,0,0,152,2,0,0,148,2,0,0,
            1,0,0,0,3,0,0,0,1,0,0,0,0,0,0,0,
            0,0,0,0,0,0,0,0,255,255,255,255,1,0,0,0,
            0,0,0,0,112,1,0,0,1,1,255,255,254,255,53,0,
            67,84,65,66,28,0,0,0,155,0,0,0,1,1,255,255,
            2,0,0,0,28,0,0,0,0,1,0,0,148,0,0,0,
            68,0,0,0,2,0,0,0,1,0,0,0,84,0,0,0,
            100,0,0,0,116,0,0,0,3,0,0,0,1,0,0,0,
            132,0,0,0,0,0,0,0,69,110,97,98,108,101,84,101,
            120,116,117,114,101,0,171,171,0,0,1,0,1,0,1,0,
            1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
            0,0,0,0,0,0,0,0,116,101,120,116,117,114,101,83,
            97,109,112,108,101,114,0,171,4,0,12,0,1,0,1,0,
            1,0,0,0,0,0,0,0,112,115,95,49,95,49,0,77,
            105,99,114,111,115,111,102,116,32,40,82,41,32,68,51,68,
            88,57,32,83,104,97,100,101,114,32,67,111,109,112,105,108,
            101,114,32,57,46,49,53,46,55,55,57,46,48,48,48,48,
            0,171,171,171,81,0,0,0,1,0,15,160,0,0,128,63,
            0,0,0,0,0,0,0,0,0,0,128,191,81,0,0,0,
            2,0,15,160,0,0,0,0,0,0,0,0,0,0,0,0,
            0,0,0,63,66,0,0,0,0,0,15,176,5,0,0,0,
            1,0,15,128,0,0,228,176,0,0,228,144,8,0,0,0,
            0,0,15,176,1,0,228,160,0,0,228,160,5,0,0,0,
            0,0,8,176,0,0,255,176,1,0,255,160,4,0,0,0,
            0,0,8,128,0,0,255,176,1,0,255,160,2,0,255,160,
            80,0,0,0,0,0,15,128,0,0,255,128,1,0,228,128,
            0,0,228,144,255,255,0,0,0,0,0,0,0,0,0,0,
            255,255,255,255,0,0,0,0,0,0,0,0,12,2,0,0,
            1,1,254,255,254,255,63,0,67,84,65,66,28,0,0,0,
            198,0,0,0,1,1,254,255,3,0,0,0,28,0,0,0,
            0,0,0,0,191,0,0,0,88,0,0,0,2,0,8,0,
            4,0,0,0,100,0,0,0,116,0,0,0,180,0,0,0,
            2,0,4,0,4,0,0,0,100,0,0,0,116,0,0,0,
            185,0,0,0,2,0,0,0,4,0,0,0,100,0,0,0,
            116,0,0,0,80,114,111,106,101,99,116,105,111,110,0,171,
            3,0,3,0,4,0,4,0,1,0,0,0,0,0,0,0,
            0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
            0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
            0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
            0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
            86,105,101,119,0,87,111,114,108,100,0,118,115,95,49,95,
            49,0,77,105,99,114,111,115,111,102,116,32,40,82,41,32,
            68,51,68,88,57,32,83,104,97,100,101,114,32,67,111,109,
            112,105,108,101,114,32,57,46,49,53,46,55,55,57,46,48,
            48,48,48,0,254,255,1,0,80,82,69,83,31,0,0,0,
            0,0,0,128,0,0,15,144,31,0,0,0,5,0,0,128,
            1,0,15,144,31,0,0,0,10,0,0,128,2,0,15,144,
            9,0,0,0,1,0,1,128,0,0,228,144,0,0,228,160,
            9,0,0,0,1,0,2,128,0,0,228,144,1,0,228,160,
            9,0,0,0,1,0,4,128,0,0,228,144,2,0,228,160,
            9,0,0,0,1,0,8,128,0,0,228,144,3,0,228,160,
            9,0,0,0,0,0,1,128,1,0,228,128,4,0,228,160,
            9,0,0,0,0,0,2,128,1,0,228,128,5,0,228,160,
            9,0,0,0,0,0,4,128,1,0,228,128,6,0,228,160,
            9,0,0,0,0,0,8,128,1,0,228,128,7,0,228,160,
            9,0,0,0,0,0,1,192,0,0,228,128,8,0,228,160,
            9,0,0,0,0,0,2,192,0,0,228,128,9,0,228,160,
            9,0,0,0,0,0,4,192,0,0,228,128,10,0,228,160,
            9,0,0,0,0,0,8,192,0,0,228,128,11,0,228,160,
            1,0,0,0,0,0,3,224,1,0,228,144,1,0,0,0,
            0,0,15,208,2,0,228,144,255,255,0,0,255,255,255,255,
            5,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,
            8,0,0,0,84,101,120,116,117,114,101,0
        };

        #endif

        #endregion

        #region XBOX Code

        #if XBOX

        private static byte[] EFFECT_CODE = new byte[]
        {
            254,255,9,1,0,0,2,192,0,0,0,0,0,0,0,3,
            0,0,0,3,0,0,0,96,0,0,0,0,0,0,0,0,
            0,0,0,4,0,0,0,4,0,0,0,0,0,0,0,0,
            0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
            0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
            0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
            0,0,0,0,0,0,0,0,0,0,0,6,87,111,114,108,
            100,0,0,0,0,0,0,3,0,0,0,3,0,0,0,200,
            0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,4,
            0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
            0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
            0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
            0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
            0,0,0,5,86,105,101,119,0,0,0,0,0,0,0,3,
            0,0,0,3,0,0,1,48,0,0,0,0,0,0,0,0,
            0,0,0,4,0,0,0,4,0,0,0,0,0,0,0,0,
            0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
            0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
            0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
            0,0,0,0,0,0,0,0,0,0,0,11,80,114,111,106,
            101,99,116,105,111,110,0,0,0,0,0,1,0,0,0,0,
            0,0,1,96,0,0,0,0,0,0,0,0,0,0,0,1,
            0,0,0,1,0,0,0,0,0,0,0,14,69,110,97,98,
            108,101,84,101,120,116,117,114,101,0,0,0,0,0,0,5,
            0,0,0,4,0,0,1,140,0,0,0,0,0,0,0,0,
            0,0,0,1,0,0,0,8,84,101,120,116,117,114,101,0,
            0,0,0,10,0,0,0,4,0,0,2,104,0,0,0,0,
            0,0,0,0,0,0,0,2,0,0,0,5,0,0,0,4,
            0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,
            0,0,0,2,0,0,0,2,0,0,0,0,0,0,0,0,
            0,0,0,0,0,0,0,1,0,0,0,1,0,0,0,1,
            0,0,0,2,0,0,0,2,0,0,0,0,0,0,0,0,
            0,0,0,0,0,0,0,1,0,0,0,1,0,0,0,1,
            0,0,0,2,0,0,0,2,0,0,0,0,0,0,0,0,
            0,0,0,0,0,0,0,1,0,0,0,1,0,0,0,4,
            0,0,0,110,0,0,0,16,0,0,1,176,0,0,1,172,
            0,0,0,117,0,0,0,16,0,0,1,200,0,0,1,196,
            0,0,0,116,0,0,0,16,0,0,1,232,0,0,1,228,
            0,0,0,115,0,0,0,16,0,0,2,8,0,0,2,4,
            0,0,0,15,116,101,120,116,117,114,101,83,97,109,112,108,
            101,114,0,0,0,0,0,3,0,0,0,16,0,0,0,4,
            0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,
            0,0,0,15,0,0,0,4,0,0,0,0,0,0,0,0,
            0,0,0,0,0,0,0,3,112,48,0,0,0,0,0,8,
            68,101,102,97,117,108,116,0,0,0,0,6,0,0,0,1,
            0,0,0,4,0,0,0,5,0,0,0,4,0,0,0,32,
            0,0,0,0,0,0,0,0,0,0,0,108,0,0,0,136,
            0,0,0,0,0,0,0,0,0,0,0,212,0,0,0,240,
            0,0,0,0,0,0,0,0,0,0,1,64,0,0,1,92,
            0,0,0,0,0,0,0,0,0,0,1,116,0,0,1,136,
            0,0,0,0,0,0,0,0,0,0,1,152,0,0,2,36,
            0,0,0,0,0,0,0,0,0,0,2,180,0,0,0,0,
            0,0,0,1,0,0,2,172,0,0,0,0,0,0,0,2,
            0,0,0,92,0,0,0,0,0,0,2,128,0,0,2,124,
            0,0,0,93,0,0,0,0,0,0,2,152,0,0,2,148,
            0,0,0,1,0,0,0,3,0,0,0,1,0,0,0,0,
            0,0,0,0,0,0,0,0,255,255,255,255,0,0,0,1,
            0,0,0,0,0,0,1,76,16,42,17,0,0,0,0,248,
            0,0,0,84,0,0,0,0,0,0,0,36,0,0,0,0,
            0,0,0,208,0,0,0,0,0,0,0,0,0,0,0,168,
            0,0,0,28,0,0,0,155,255,255,3,0,0,0,0,2,
            0,0,0,28,0,0,0,0,0,0,0,148,0,0,0,68,
            0,0,0,0,0,1,0,0,0,0,0,84,0,0,0,100,
            0,0,0,116,0,3,0,0,0,1,0,0,0,0,0,132,
            0,0,0,0,69,110,97,98,108,101,84,101,120,116,117,114,
            101,0,171,171,0,0,0,1,0,1,0,1,0,1,0,0,
            0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
            0,0,0,0,116,101,120,116,117,114,101,83,97,109,112,108,
            101,114,0,171,0,4,0,12,0,1,0,1,0,1,0,0,
            0,0,0,0,112,115,95,51,95,48,0,50,46,48,46,56,
            50,55,53,46,48,0,171,171,0,0,0,0,0,0,0,84,
            16,0,1,0,0,0,0,8,0,2,0,0,0,0,24,66,
            0,1,0,3,0,0,0,1,0,0,48,80,0,0,241,160,
            0,0,0,4,16,3,178,0,18,0,0,1,0,0,0,0,
            16,4,196,0,34,0,0,0,0,0,0,0,16,5,196,0,
            34,0,0,0,16,8,0,1,31,31,246,136,0,0,64,0,
            200,15,128,0,0,0,0,0,225,0,1,0,200,15,128,0,
            0,0,0,0,226,1,1,0,0,0,0,0,0,0,0,0,
            0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,
            0,0,0,0,0,0,0,0,0,0,2,60,16,42,17,1,
            0,0,1,64,0,0,0,252,0,0,0,0,0,0,0,36,
            0,0,0,0,0,0,0,252,0,0,0,0,0,0,0,0,
            0,0,0,212,0,0,0,28,0,0,0,198,255,254,3,0,
            0,0,0,3,0,0,0,28,0,0,0,0,0,0,0,191,
            0,0,0,88,0,2,0,8,0,4,0,0,0,0,0,100,
            0,0,0,116,0,0,0,180,0,2,0,4,0,4,0,0,
            0,0,0,100,0,0,0,116,0,0,0,185,0,2,0,0,
            0,4,0,0,0,0,0,100,0,0,0,116,80,114,111,106,
            101,99,116,105,111,110,0,171,0,3,0,3,0,4,0,4,
            0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
            0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
            0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
            0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
            0,0,0,0,0,0,0,0,86,105,101,119,0,87,111,114,
            108,100,0,118,115,95,51,95,48,0,50,46,48,46,56,50,
            55,53,46,48,0,171,171,171,0,0,0,0,0,0,0,252,
            0,17,0,3,0,0,0,0,0,0,0,0,0,0,24,66,
            0,0,0,1,0,0,0,3,0,0,0,2,0,0,2,144,
            0,16,0,3,0,0,80,4,0,48,160,5,0,0,48,80,
            0,1,241,160,0,0,16,18,0,0,16,19,112,21,48,3,
            0,0,18,0,194,0,0,0,0,0,96,6,96,12,18,0,
            18,0,0,0,0,0,0,0,32,18,196,0,34,0,0,0,
            5,248,32,0,0,0,6,136,0,0,0,0,5,248,16,0,
            0,0,15,200,0,0,0,0,5,248,0,0,0,0,6,136,
            0,0,0,0,200,1,0,3,0,167,167,0,175,2,0,0,
            200,2,0,3,0,167,167,0,175,2,1,0,200,4,0,3,
            0,167,167,0,175,2,2,0,200,8,0,3,0,167,167,0,
            175,2,3,0,200,1,0,2,0,167,167,0,175,3,4,0,
            200,2,0,2,0,167,167,0,175,3,5,0,200,4,0,2,
            0,167,167,0,175,3,6,0,200,8,0,2,0,167,167,0,
            175,3,7,0,200,1,128,62,0,167,167,0,175,2,8,0,
            200,2,128,62,0,167,167,0,175,2,9,0,200,4,128,62,
            0,167,167,0,175,2,10,0,200,8,128,62,0,167,167,0,
            175,2,11,0,200,3,128,0,0,176,176,0,226,1,1,0,
            200,15,128,1,0,0,0,0,226,0,0,0,0,0,0,0,
            0,0,0,0,0,0,0,0,255,255,255,255,0,0,0,5,
            0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,8,
            84,101,120,116,117,114,101,0
        }

        #endif

        #endregion

        #endregion

        #endregion

        #endregion

        #region Properties

        /// <summary>
        /// Gets or Sets the world matrix value for this effect.
        /// </summary>
        public Matrix World
        {
            get { return _World; }
            set
            {
                if (_World != value)
                {
                    _World = value;
                    WorldParameter.SetValue(_World);
                }
            }
        }

        /// <summary>
        /// Gets or Sets the view matrix value for this effect.
        /// </summary>
        public Matrix View
        {
            get { return _View; }
            set
            {
                if (_View != value)
                {
                    _View = value;
                    ViewParameter.SetValue(_View);
                }
            }
        }

        /// <summary>
        /// Gets or Sets the projection matrix value for this effect.
        /// </summary>
        public Matrix Projection
        {
            get { return _Projection; }
            set
            {
                if (_Projection != value)
                {
                    _Projection = value;
                    ProjectionParameter.SetValue(_Projection);
                }
            }
        }

        /// <summary>
        /// Gets or sets a value indicating this effect should use Textures.
        /// </summary>
        public bool EnableTextures
        {
            get { return _EnableTexture; }
            set
            {
                _EnableTexture = value;
                EnableTextureParameter.SetValue(_EnableTexture);
            }
        }

        /// <summary>
        /// Gets or Sets the Texture set for this effect.
        /// </summary>
        public Texture2D Texture
        {
            get { return _Texture; }
            set
            {
                if (_Texture != value)
                {
                    _Texture = value;
                    TextureParameter.SetValue(_Texture);
                }
            }
        }

        #endregion

        #region Methods

        #region Constructor(s)

        /// <summary>
        /// Constructs a new instance of this object.
        /// </summary>
        /// <param name="graphicsDevice">The graphics device to use when creating this object.</param>
        /// <param name="effectPool">The effect pool to share resources from</param>
        public SpriteEffect(GraphicsDevice graphicsDevice, EffectPool effectPool)
            : base(graphicsDevice, EFFECT_CODE, CompilerOptions.Debug, effectPool)
        {
            WorldParameter = Parameters["World"];
            _World = Matrix.CreateTranslation(Vector3.Zero);
            WorldParameter.SetValue(_World);

            ViewParameter = Parameters["View"];
            ViewParameter.SetValue(_View);

            ProjectionParameter = Parameters["Projection"];
            ProjectionParameter.SetValue(_Projection);

            EnableTextureParameter = Parameters["EnableTexture"];
            EnableTextureParameter.SetValue(true);

            TextureParameter = Parameters["Texture"];
        }

        #endregion

        #endregion
    }
}
